#ifndef G3_CISTREAM_H
#define G3_CISTREAM_H

#include "f_stream.h"

#include <boost/circular_buffer.hpp>

namespace G3 {

class CISTREAM: public G3::STREAM {
	public:
		CISTREAM (ulong reservedSpace = 5242880);
		~CISTREAM ();

		G3::STREAM::CHUNK GetChunk (long maxSize = -1);

		byte *GetDataPointer ();

//==============================================================================
// Sets stream caret position
//
//		long Offset				File position to seek for
//
//		STREAM_SEEK_FLAG Flag
//			STREAM_BEGINNING	File position caret is reset to the beginning of
//								current stream buffer
//
//			STREAM_SET			Sets file position to Offset
//
//          STREAM_MOVE         Moves file position by Offset
//
//			STREAM_END			File position caret is moved to the end of the
//								stream
//
//	Returns true on success
//==============================================================================
		bool Seek (long offset, STREAM_SEEK_FLAG flag);

//==============================================================================
// Tells the stream caret position
//
//		STREAM_SEEK_FLAG Flag
//			STREAM_GET			Tells the CaretPosition of the stream
//
//			STREAM_END			Tells the size of the stream
//
//          STREAM_SIZE         Tells the amount of memory reserved for the stream
//
//	Returns the position in bytes or -1 if the input was invalid
//==============================================================================
		long Tell (STREAM_SEEK_FLAG flag);

//==============================================================================
// Returns true if End Of File was encountered
//==============================================================================
		bool EndOfFile ();

//==============================================================================
// Resizes the stream buffer
//==============================================================================
		void Resize (long size);

//==============================================================================
// Reads data from the stream
//
//		void *Pointer			Pointer to a memory block where the data is stored
//
//		long Size				Number of bytes read from the stream
//
//	Returns the number of bytes read
//==============================================================================
		long Read (byte *pointer, long size, bool wrap_around = false);

//==============================================================================
// Reads a line from the stream. End of a line can be overridden..
//
//		char *Delimiters		End of line characters
//				"\r\n"			This is the default
//
//	Returns, what it was able to read from the stream until \r\n or EOF
//==============================================================================
		std::string Readline (const std::string delimiters = "\r\n");

//==============================================================================
// Reads data from the stream and saves it into a file
//
//		const char *Filename	Name of the file to store the data in
//
//		long Size				Number of bytes read from the stream
//				-1, 0			Reads the whole stream buffer
//
//		long Position			Where to write into the file
//
//	Returns the number of bytes read
//==============================================================================
		long ReadToFile (const std::string &filename, long size = -1, long position = 0);

//==============================================================================
// Flushes the whole stream
//==============================================================================
		bool Flush ();

//==============================================================================
// Adds to the stream buffer
//
//		void *Pointer			Pointer to a memory block from where to buffer
//
//		long Size				Number of bytes to buffer
//
//	Returns Size on success
//==============================================================================
		long Buffer (byte *pointer, long size);

//==============================================================================
// Buffers a file to the stream
//
//		const char *Filename	Name of the file to buffer
//
//		long Size				Number of bytes to buffer
//				-1, 0			Buffers the whole file into the stream
//
//		long Position			Where in the file should we start reading
//
//	Returns true on success
//==============================================================================
		long BufferFromFile (const std::string &filename, long size = -1, long position = 0);

//==============================================================================
// Prints into the buffer
//==============================================================================
		long BufferPrint (const char *fmt, ...);

		void DumpToLog ();

	protected:
        boost::circular_buffer_space_optimized<byte> data;

        long caretPos;

        // Number of bytes buffered in total
		long TotalSize;

		bool passedEOF;
};

}

#endif
